package itsm.isperp.module.service.app;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.quartz.domain.JobHistory;
import itsm.isperp.framework.quartz.listener.JobExecutionHistoryListener;
import itsm.isperp.framework.quartz.repository.JobHistoryMapper;
import itsm.isperp.framework.quartz.service.ISchedulerService;
import itsm.isperp.framework.quartz.service.Initializer;
import itsm.isperp.module.entity.app.AppJobHistory;
import itsm.isperp.module.repository.app.AppJobHistoryMapper;

import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.simpl.SimpleThreadPool;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 */
@Service
public class AppJobSchedulerService implements ISchedulerService,
		DisposableBean {
	protected boolean runJobInCurrentInstance = true;
	protected Scheduler scheduler;
	protected int threadCount = 10;
	private final Log logger = LogFactory.getLog(AppJobSchedulerService.class);

	@Autowired
	protected AppJobHistoryMapper appJobHistoryMapper;

	@Override
	public Scheduler retrieveScheduler() throws SchedulerException {
		if (scheduler == null) {
			scheduler = newScheduler();
		}
		return scheduler;
	}

	@Override
	public Scheduler getCurrentScheduler() throws SchedulerException {
		return scheduler;
	}

	private Scheduler newScheduler() throws SchedulerException {
		StdSchedulerFactory factory = new StdSchedulerFactory();
		Properties mergedProps = new Properties();
		mergedProps.setProperty(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
				SimpleThreadPool.class.getName());
		mergedProps.setProperty("org.quartz.scheduler.instanceName",
				"ISPERPScheduler");
		mergedProps.setProperty("org.quartz.scheduler.instanceId",
				"CoreISPERPScheduler");
		mergedProps.setProperty("org.quartz.threadPool.threadCount",
				Integer.toString(threadCount));

		factory.initialize(mergedProps);
		Scheduler scheduler = factory.getScheduler();

		JobExecutionHistoryListener l = new JobExecutionHistoryListener(
				(JobHistoryMapper) this.appJobHistoryMapper) {

			@Override
			public JobHistory getJobHistory() {
				return new AppJobHistory();
			}
		};
		scheduler.getListenerManager().addJobListener(l);
		return scheduler;
	}

	public boolean isRunJobInCurrentInstance() {
		return runJobInCurrentInstance;
	}

	public void setRunJobInCurrentInstance(boolean runJobInCurrentInstance) {
		this.runJobInCurrentInstance = runJobInCurrentInstance;
	}

	public String getJobApplicationName() {
		return "isperp.jobApplicationName";
	}

	public void resetScheduer() throws Exception {
		if (scheduler != null && !scheduler.isShutdown()) {
			scheduler.shutdown(false);
		}
		this.scheduler = this.newScheduler();
		Initializer initializer = (Initializer) ContextHolder
				.getSpringBean(Initializer.BEAN_ID);
		initializer.initRunJobsForStartup();
		initializer.initSystemJobs();
		if (this.scheduler.isInStandbyMode()) {
			this.scheduler.start();
		}
	}

	public String getJobInstanceName() {
		String jobApplicationName = getJobApplicationName();
		if (StringUtils.isEmpty(jobApplicationName)) {
			return System.getProperty(JOB_INSTANCE_NAME);
		} else {
			return System.getProperty(jobApplicationName + "."
					+ JOB_INSTANCE_NAME);
		}
	}

	public int getThreadCount() {
		return threadCount;
	}

	public void setThreadCount(int threadCount) {
		this.threadCount = threadCount;
	}

	@Override
	public void destroy() throws SchedulerException {
		if (scheduler != null && !scheduler.isShutdown()) {
			logger.info("Shutting down Quartz Scheduler");
			scheduler.shutdown(false);
		}
	}
}
